/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.screw.engine;

import static org.elsfs.cloud.common.util.lang.FileUtils.getFileByPath;
import static org.elsfs.cloud.common.util.lang.FileUtils.isFileExists;
import static org.elsfs.cloud.screw.constant.ScrewConstants.DEFAULT_ENCODING;
import static org.elsfs.cloud.screw.constant.ScrewConstants.DEFAULT_LOCALE;
import static org.elsfs.cloud.screw.engine.EngineTemplateType.freemarker;

import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.Objects;
import org.elsfs.cloud.common.util.exception.ProduceException;
import org.elsfs.cloud.common.util.lang.Assert;
import org.elsfs.cloud.common.util.lang.ExceptionUtils;
import org.elsfs.cloud.common.util.lang.StringUtils;
import org.elsfs.cloud.screw.metadata.model.DataModel;

/**
 * freemarker template produce
 *
 * @author zeng
 */
public class FreemarkerTemplateEngine extends AbstractTemplateEngine {
  /** freemarker 配置实例化 */
  private final Configuration configuration =
      new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);

  {
    try {
      String path = getEngineConfig().getCustomTemplate();
      // 自定义模板
      if (StringUtils.isNotBlank(path) && isFileExists(path)) {
        // 获取父目录
        String parent = Objects.requireNonNull(getFileByPath(path)).getParent();
        // 设置模板加载路径
        configuration.setDirectoryForTemplateLoading(new File(parent));
      } else {
        // 加载自带模板
        // 模板存放路径
        configuration.setTemplateLoader(
            new ClassTemplateLoader(this.getClass(), freemarker.getTemplateDir()));
      }
      // 编码
      configuration.setDefaultEncoding(DEFAULT_ENCODING);
      // 国际化
      configuration.setLocale(new Locale(DEFAULT_LOCALE));
    } catch (Exception e) {
      throw ExceptionUtils.mpe(e);
    }
  }

  public FreemarkerTemplateEngine(EngineConfig templateConfig) {
    super(templateConfig);
  }

  /**
   * 生成文档
   *
   * @param info {@link DataModel}
   * @throws ProduceException ProduceException
   */
  @Override
  public ByteArrayOutputStream produce(DataModel info, String docName) throws ProduceException {
    Assert.notNull(info, "DataModel can not be empty!");
    String path = getEngineConfig().getCustomTemplate();
    try {
      Template template;
      // freemarker template
      // 如果自定义路径不为空文件也存在
      if (StringUtils.isNotBlank(path) && isFileExists(path)) {
        // 文件名称
        String fileName = new File(path).getName();
        template = configuration.getTemplate(fileName);
      } else {
        // 获取系统默认的模板
        template =
            configuration.getTemplate(
                getEngineConfig().getFileType().getTemplateNamePrefix() + freemarker.getSuffix());
      }
      // writer freemarker

      try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
          Writer out = new BufferedWriter(new OutputStreamWriter(outputStream, DEFAULT_ENCODING))) {
        // process
        template.process(info, out);
        return outputStream;
      }
    } catch (IOException | TemplateException e) {
      throw ExceptionUtils.mpe(e);
    }
  }
}
